import _ from 'lodash';
import StorageHelper from '@CIF/Runtime/Global/storage';
import { RUNTIME_CFG_ENUM } from '@CIF/Runtime/Global/variable';
import { DelayTaskQueue } from './util';
import { ElMessage, ElNotification } from 'element-plus';

class Notifier {
	/**
	 * 一次远程获取组件数量
	 *
	 * @memberof Notifier
	 */
	countOfRemoteLoadingAssets = 0;
	/**
	 *当前已下载组件数量
	 *
	 * @memberof Notifier
	 */
	fetchedComponentsCount = 0;
	fetchingProgress = 0;

	fetchingProgressListenersQueue = [];
	loadingFinishListenersQueue = [];
	loadingStartListenersQueue = [];

	channelStation = {};

	addsToCountOfRemoteLoadingAssets(rlaNumber = 0) {
		this.countOfRemoteLoadingAssets += rlaNumber;
	}

	updateFetchingProgress(step = 1) {
		if (this.countOfRemoteLoadingAssets === 0) {
			if (_.get(window, 'cif.config.logger.enable', false) === true) {
				console.log('CIF.U.Notifier:updateFetchingProgress 远程加载资源数量为0');
			}
			return;
		}
		this.fetchedComponentsCount += step;
		this.fetchingProgress = this.fetchedComponentsCount / this.countOfRemoteLoadingAssets;
		this.fireComponentFetchingProgressNotification();
	}

	fireComponentFetchingProgressNotification() {
		const fetchingProgress =
			this.countOfRemoteLoadingAssets !== 0 ? this.fetchingProgress * 100 : 100;
		this.fetchingProgressListenersQueue.forEach((listener) => {
			listener(fetchingProgress);
		});
	}

	notifyComponentFetchingPercent(listener = () => {}, id = '') {
		let unNotify = true;
		let oldListener = null;
		if (!_.isNil(id)) {
			for (let i = 0; i < this.fetchingProgressListenersQueue.length; i++) {
				oldListener = this.fetchingProgressListenersQueue[i];
				if (oldListener.id === id || oldListener === listener) {
					unNotify = false;
					listener.id = id;
					this.fetchingProgressListenersQueue[i] = listener;
					return;
				}
			}
		}
		if (unNotify) {
			id && (listener.id = id);
			this.fetchingProgressListenersQueue.push(listener);
		}
	}

	fireComponentFinishLoadingNotification(now = 'later') {
		if (_.isString(now) && _.isEqual(now, 'now')) {
			this.loadingFinishListenersQueue.forEach((listener) => {
				listener();
			});
		} else {
			if (this.countOfRemoteLoadingAssets === 0) {
				this.loadingFinishListenersQueue.forEach((listener) => {
					listener();
				});
			} else {
				let timer = setInterval(() => {
					if (this.fetchingProgress >= 1) {
						this.loadingFinishListenersQueue.forEach((listener) => {
							listener();
						});
						clearInterval(timer);
						timer = null;
					}
				}, 50);
			}
		}
	}

	notifyWhenComponentFinishLoading(listener = () => {}, id = '') {
		let unNotify = true;
		let oldListener = null;
		if (!_.isNil(id)) {
			for (let i = 0; i < this.loadingFinishListenersQueue.length; i++) {
				oldListener = this.loadingFinishListenersQueue[i];
				if (oldListener.id === id || oldListener === listener) {
					unNotify = false;
					listener.id = id;
					this.loadingFinishListenersQueue[i] = listener;
					return;
				}
			}
		}
		if (unNotify) {
			id && (listener.id = id);
			this.loadingFinishListenersQueue.push(listener);
		}
	}

	fireComponentStartLoadingNotification() {
		this.loadingStartListenersQueue.forEach((listener) => {
			listener();
		});
	}

	notifyWhenStartFetching(listener = () => {}, id = '') {
		let unNotify = true;
		let oldListener = null;
		if (!_.isNil(id)) {
			for (let i = 0; i < this.loadingStartListenersQueue.length; i++) {
				oldListener = this.loadingStartListenersQueue[i];
				if (oldListener.id === id || oldListener === listener) {
					unNotify = false;
					listener.id = id;
					this.loadingStartListenersQueue[i] = listener;
					return;
				}
			}
		}
		if (unNotify) {
			id && (listener.id = id);
			this.loadingStartListenersQueue.push(listener);
		}
	}

	listenToChannel(channelName = '', listener = () => {}, id = '') {
		let channel = this.channelStation[channelName];
		if (_.isNil(channel)) {
			channel = [];
			this.channelStation[channelName] = channel;
		}

		let unNotify = true;
		let oldListener = null;
		if (!_.isNil(id)) {
			for (let i = 0; i < channel.length; i++) {
				oldListener = channel[i];
				// *采用身份占用机制，替换旧监听者
				if (oldListener.id === id || oldListener === listener) {
					unNotify = false;
					listener.id = id;
					channel[i] = listener;
					return;
				}
			}
		}
		if (unNotify) {
			id && (listener.id = id);
			channel.push(listener);
		}
	}

	broadcastInChannel(channelName = '', message) {
		let channel = this.channelStation[channelName];
		if (_.isNil(channel)) {
			channel = [];
			this.channelStation[channelName] = channel;
			if (_.get(window, 'cif.config.logger.enable', false) === true) {
				console.log(
					`CIF.U.Notifier:broadcastInChannel 广播消息失败，CIF Notifier未发现频道：${channelName}`
				);
			}
			return;
		} else {
			// let listener = null
			channel.forEach((listener, index) => {
				listener(message, index);
			});
			// let i = 0
			// for(i = 0; i < channel.length; i++) {
			//   listener = channel[i]
			//   listener.async ? await listener(message, i) : listener(message, i)
			// }
			// channel.forEach((listener) => {
			//   listener(message)
			// })
		}
	}

	resetComponentFetchingPercentListener() {
		this.fetchingProgressListenersQueue = [];
	}

	resetComponentFinishLoadingListener() {
		this.loadingFinishListenersQueue = [];
	}

	resetComponentStartLoadingListener() {
		this.loadingStartListenersQueue = [];
	}

	resetFetchingProgress() {
		this.fetchedComponentsCount = 0;
		this.fetchingProgress = 0;
		this.countOfRemoteLoadingAssets = 0;
	}

	resetNotifier() {
		this.resetFetchingProgress();
		this.resetComponentFetchingPercentListener();
		this.resetComponentFinishLoadingListener();
		this.resetComponentStartLoadingListener();
	}
}

const notifierInst = new Notifier();

const delayTaskQueue = new DelayTaskQueue(5);

notifierInst.listenToChannel(
	'_damage_cpnt_channel',
	(message, index) => {
		delayTaskQueue.appendTask(() => {
			const mode = StorageHelper.get(RUNTIME_CFG_ENUM.CIF_MODE);
			if (mode === RUNTIME_CFG_ENUM.PRODUCTION_MODE) {
				ElNotification.error({
					title: `警告！${message}组件已损毁`,
					message: '该组件及其子组件将被跳过加载',
					position: 'bottom-left'
				});
			} else {
				ElMessage({
					type: 'error',
					message: `警告！${message}组件已损毁，该组件及其子组件将被跳过加载`
				});
			}
		}, 20);
	},
	'_damage_cpnt_listener',
	true
);

export default notifierInst;
